package org.dromara.common.security.handler;

import cn.hutool.core.util.ReUtil;
import org.dromara.common.core.utils.SpringUtils;
import lombok.Data;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.*;
import java.util.regex.Pattern;


/**
 * @Author 刘武贵
 * @Date 2024/8/15 22:00
 * @Description 功能描述：获取所有Url配置
 */
/**
 * AllUrlHandler 类是 InitializingBean 接口的实现类，用于处理所有URL请求.
 * 该类通过实现 InitializingBean 接口，提供了在 Spring 容器初始化之后执行自定义初始化逻辑的能力.
 */
@Data
public class AllUrlHandler implements InitializingBean {

    /**
     * 定义一个正则表达式模式，用于匹配和提取URL模式
     */
    private static final Pattern PATTERN = Pattern.compile("\\{(.*?)\\}");

    /**
     * 存储匹配到的URLs的列表
     */
    private List<String> urls = new ArrayList<>();

    /**
     * 在所有属性设置之后执行，用于初始化所有拦截器
     * 此方法覆盖了父类方法，用于在服务启动时获取所有请求映射信息
     */
    @Override
    public void afterPropertiesSet() {
        // 创建一个无重复元素集合，用于存储处理后的URL模式
        Set<String> set = new HashSet<>();
        // 通过SpringUtils工具获取RequestMappingHandlerMapping类型的bean
        RequestMappingHandlerMapping mapping = SpringUtils.getBean("requestMappingHandlerMapping", RequestMappingHandlerMapping.class);
        // 获取映射的处理器方法集合
        Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
        // 遍历处理器方法集合的键（RequestMappingInfo对象）
        map.keySet().forEach(info -> {
            // 获取注解上边的 path 替代 path variable 为 *
            // 获取请求映射的路径模式条件，并确保不为空
            Objects.requireNonNull(info.getPathPatternsCondition().getPatterns())
                    // 遍历路径模式，将具体的路径变量替换为通配符*
                    .forEach(url -> set.add(ReUtil.replaceAll(url.getPatternString(), PATTERN, "*")));
        });
        // 将处理后的URL模式集合合并到成员变量urls中
        urls.addAll(set);
    }

}
